//
//  NetworkManager.swift
//  swift_review
//
//  Created by Andrew on 2024/11/25.
//

import UIKit

enum HTTPMethod: String {
    case GET
    case POST
    case PUT
    case DELETE
}

struct NetworkManager {
    /// 发起网络请求
    /// - Parameters:
    ///   - urlString: 请求的 URL 字符串
    ///   - method: HTTP 请求方法
    ///   - parameters: 请求参数（字典）
    ///   - completion: 请求结果回调（成功返回数据，失败返回错误）
    static func request(
        urlString: String,
        method: HTTPMethod,
        parameters: [String: Any]?,
        completion: @escaping (Result<Data, Error>) -> Void
    ) {
        // 1. 检查 URL 是否有效
        guard let url = URL(string: urlString) else {
            completion(.failure(NSError(domain: "Invalid URL", code: 400, userInfo: nil)))
            return
        }
        
        // 2. 创建 URLRequest 对象
        var request = URLRequest(url: url)
        request.httpMethod = method.rawValue
        
        // 3. 根据方法类型设置请求体（仅适用于 POST/PUT）
        if let parameters = parameters, method == .POST || method == .PUT {
            do {
                request.httpBody = try JSONSerialization.data(withJSONObject: parameters, options: [])
                request.addValue("application/json", forHTTPHeaderField: "Content-Type")
            } catch {
                completion(.failure(error))
                return
            }
        }
        
        // 4. 发起请求
        let task = URLSession.shared.dataTask(with: request) { data, response, error in
            // 检查错误
            if let error = error {
                completion(.failure(error))
                return
            }
            
            // 检查响应
            if let httpResponse = response as? HTTPURLResponse, !(200...299).contains(httpResponse.statusCode) {
                let error = NSError(domain: "HTTP Error", code: httpResponse.statusCode, userInfo: nil)
                completion(.failure(error))
                return
            }
            
            // 返回数据
            if let data = data {
                completion(.success(data))
            } else {
                completion(.failure(NSError(domain: "No Data", code: 404, userInfo: nil)))
            }
        }
        
        task.resume()
    }
}

struct NetworkHander {
    /// 发起网络请求
    /// - Parameters:
    ///   - urlString: 请求的 URL 字符串
    ///   - method: HTTP 请求方法
    ///   - parameters: 请求参数（字典）
    ///   - completion: 请求结果回调（成功返回解码对象，失败返回错误）
    static func request<T: Decodable>(
        urlString: String,
        method: HTTPMethod,
        parameters: [String: Any]?,
        completion: @escaping (Result<T, Error>) -> Void
    ) {
        // 1. 检查 URL 是否有效
        guard let url = URL(string: urlString) else {
            completion(.failure(NSError(domain: "Invalid URL", code: 400, userInfo: nil)))
            return
        }

        // 2. 创建 URLRequest 对象
        var request = URLRequest(url: url)
        request.httpMethod = method.rawValue

        // 3. 根据方法类型设置请求体（仅适用于 POST/PUT）
        if let parameters = parameters, method == .POST || method == .PUT {
            do {
                request.httpBody = try JSONSerialization.data(withJSONObject: parameters, options: [])
                request.addValue("application/json", forHTTPHeaderField: "Content-Type")
            } catch {
                completion(.failure(error))
                return
            }
        }

        // 4. 发起请求
        let task = URLSession.shared.dataTask(with: request) { data, response, error in
            // 检查错误
            if let error = error {
                completion(.failure(error))
                return
            }

            // 检查响应
            if let httpResponse = response as? HTTPURLResponse, !(200...299).contains(httpResponse.statusCode) {
                let error = NSError(domain: "HTTP Error", code: httpResponse.statusCode, userInfo: nil)
                completion(.failure(error))
                return
            }

            // 解析返回数据
            if let data = data {
                do {
                    let decodedObject = try JSONDecoder().decode(T.self, from: data)
                    completion(.success(decodedObject))
                } catch {
                    completion(.failure(error))
                }
            } else {
                completion(.failure(NSError(domain: "No Data", code: 404, userInfo: nil)))
            }
        }

        task.resume()
    }
}
